#include "projectexplorer.h"
#include "ui_projectexplorer.h"

#include <QInputDialog>
#include <QString>
#include <QStringList>
#include <QDebug>
#include <QAbstractItemDelegate>
#include <QItemDelegate>
#include <QItemSelectionModel>
#include <QModelIndexList>
#include <QMessageBox>

#include "sk_game_item.h"
#include "sk_game_item_property.h"
#include "sk_game_model.h"
#include "sk_game_project.h"
#include "sk_project_item.h"
#include "sk_creation_params.h"

#include "userdata.h"
#include "mainwindow.h"
#include "leveleditor.h"
#include "designwindow.h"

class QPainter;

class NoEditDelegate : public QItemDelegate
{
public:

    NoEditDelegate(QObject * p)
        :
    QItemDelegate(p)
    {
    }

    QWidget *createEditor(QWidget *,
                                  const QStyleOptionViewItem &,
                                  const QModelIndex &) const
    {
        return 0;
    }

};

class PropertyDelegate : public QItemDelegate
{
public:

    PropertyDelegate(QObject * p)
        :
    QItemDelegate(p)
    {
    }

    void paint(QPainter * painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
         sk::GameItemProperty * p = reinterpret_cast<sk::GameItemProperty *>(index.data().toLongLong());
         if (p) p->paint(painter, option);
    }

    QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem &, const QModelIndex & index) const
    {
        Q_UNUSED(parent);
        sk::GameItemProperty * p = reinterpret_cast<sk::GameItemProperty *>(index.data().toLongLong());
        if (p) return p->createEditor(parent);
        return 0;
    }

    void setEditorData(QWidget * editor, const QModelIndex &index) const
    {
        sk::GameItemProperty * p = reinterpret_cast<sk::GameItemProperty *>(index.data().toLongLong());
        if (p) p->setEditorData(editor);
    }

    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
    {
        sk::GameItemProperty * p = reinterpret_cast<sk::GameItemProperty *>(index.data().toLongLong());
        if (p) p->setPropertyData(editor);
    }

};


ProjectExplorer::ProjectExplorer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ProjectExplorer)
{
    ui->setupUi(this);
    setLayout(ui->mainLayout);
    ui->propertiesTable->setColumnCount(2);
    ui->propertiesTable->setRowCount(0);
    ui->propertiesTable->setItemDelegateForColumn(0, new NoEditDelegate(this));
    ui->propertiesTable->setItemDelegateForColumn(1, new PropertyDelegate(this));
    QStringList headerLables;
    headerLables << QString(tr("Property")) << QString(tr("Value"));
    ui->propertiesTable->setHorizontalHeaderLabels(headerLables);
    ui->projectView->setExpandsOnDoubleClick(false);
    _propertyItem = 0;

}

void ProjectExplorer::setModel(QAbstractItemModel * model)
{
    ui->projectView->setModel(model);
}

void ProjectExplorer::setItemDelegate(QAbstractItemDelegate * delegate)
{
    ui->projectView->setItemDelegate(delegate);
}

ProjectExplorer::~ProjectExplorer()
{
    _clearProperties();
    delete ui;
}

void ProjectExplorer::on_btnNew_clicked()
{
    bool isOk;
    QString name = QInputDialog::getText(this, tr("Level name"), tr("Enter level name"), QLineEdit::Normal, QString(tr("unnamed")), &isOk);
    if (!isOk || name.isEmpty())
    {
        return;
    }
	sk::SimpleItemParam p;
	p.type = sk::IT_LEVEL;
	p.param = &name;
	_UD.mw->model()->create(_UD.pi, &p);    
}

void ProjectExplorer::_clearProperties()
{
    _propertyItem = 0;
    int n = ui->propertiesTable->rowCount();
    for (int i = 0; i < n; ++i)
    {
        sk::GameItemProperty * p = reinterpret_cast<sk::GameItemProperty *>(ui->propertiesTable->itemAt(i, 1)->data(Qt::DisplayRole).toLongLong());
        if (p)
        {
            delete p;
        }
    }
    ui->propertiesTable->setRowCount(0);
}


void ProjectExplorer::updateProperty(QString name)
{
    QAbstractItemModel * m = ui->propertiesTable->model();
    for (int ind = 0; ind < m->rowCount(); ++ind)
    {
        if (m->data(m->index(ind, 0)).toString() == name)
        {
            QString d = m->data(m->index(ind, 1)).toString();
            m->setData(m->index(ind, 1), "0");
            m->setData(m->index(ind, 1), d);
            return;
        }
    }
}

void ProjectExplorer::loadProperties(sk::GameItem * item)
{
    if (_propertyItem == item)
{
        return;
    }
    _clearProperties();
    _propertyItem = item;
    Q_ASSERT(item);
    int n = item->numProperties();
    for (int i = 0; i < n; ++i)
    {
        sk::GameItemProperty * p = item->getProperty(n - i - 1);
        Q_ASSERT(p);
        ui->propertiesTable->insertRow(0);
        ui->propertiesTable->setItem(0, 0, new QTableWidgetItem(p->name));
        ui->propertiesTable->setItem(0, 1, new QTableWidgetItem(QString::number(qlonglong(p))));
    }
}

void ProjectExplorer::on_projectView_doubleClicked(QModelIndex index)
{
    //sk::GameItem * item = reinterpret_cast<sk::GameItem *>(index.data().toLongLong());

}

void ProjectExplorer::on_projectView_clicked(QModelIndex index)
{
     sk::GameItem * item = reinterpret_cast<sk::GameItem *>(index.data().toLongLong());
    loadProperties(item);

	sk::LevelItem * l = static_cast<sk::LevelItem *>(item->getUpward(sk::IT_Level));	
	if (l)
	{
		_UD.le->setLevelItem(l);
	}
    _UD.le->setDesign();
    // todo : rename
    //item->onDoubleClickInProjectExplorer();
}

void ProjectExplorer::on_btnDelete_clicked()
{
    QModelIndexList l = ui->projectView->selectionModel()->selectedIndexes();
    if (l.isEmpty())
    {
        return;
    }
    sk::GameItem * item = reinterpret_cast<sk::GameItem *>(l.front().data().toLongLong());

    if (!item->canDeleteFromProjectExplorer())
    {
        QMessageBox::critical(this, tr("Error"), tr("Can not delete this item"));
        return;
    }
    _clearProperties();
    ui->projectView->selectionModel()->clearSelection();
    if (item->type() == sk::IT_Level)
    {
        _UD.le->setLevelItem(0);
    }
    _UD.mw->model()->remove(item);
    _UD.mw->project()->setDirty(true);
}

void ProjectExplorer::activate(sk::GameItem * item)
{
    select(item);
    loadProperties(item);    
}

void ProjectExplorer::select(sk::GameItem * item)
{
    QModelIndex ind = _UD.mw->model()->getIndex(item);
    ui->projectView->selectionModel()->select(ind, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
    ui->projectView->scrollTo(ind);
    _UD.le->setDesign();
}


void ProjectExplorer::on_btnDown_clicked()
{
    QModelIndexList l = ui->projectView->selectionModel()->selectedIndexes();
    if (l.isEmpty())
    {
        return;
    }
    sk::GameItem * item = reinterpret_cast<sk::GameItem *>(l.front().data().toLongLong());
    sk::GameItem * p = item->parent();
    if (0 == p || !p->canSwapChilds())
    {
        return;
    }
    int i = item->index();
    int j = i + 1;

	if (p->validIndexesForSwap(i, j))
	{
		ui->projectView->collapse(l.front());
		ui->projectView->collapse(_UD.mw->model()->getIndex(p->child(j)));
	}

    if (p->swapChilds(i, j))
    {
        _UD.mw->model()->onSwapItems(p, i, j);
        sk::GameItem * i = p->child(j);
        select(i);
        _clearProperties();
        loadProperties(i);
    }
}

void ProjectExplorer::on_btnUp_clicked()
{
	QModelIndexList l = ui->projectView->selectionModel()->selectedIndexes();
	if (l.isEmpty())
	{
		return;
	}
	sk::GameItem * item = reinterpret_cast<sk::GameItem *>(l.front().data().toLongLong());
	sk::GameItem * p = item->parent();
	if (0 == p || !p->canSwapChilds())
	{
		return;
	}
	int i = item->index();
	int j = i - 1;

	if (p->validIndexesForSwap(i, j))
	{
		ui->projectView->collapse(l.front());
		ui->projectView->collapse(_UD.mw->model()->getIndex(p->child(j)));
	}

	if (p->swapChilds(i, j))
	{
		_UD.mw->model()->onSwapItems(p, i, j);
		sk::GameItem * i = p->child(j);
		select(i);
		_clearProperties();
		loadProperties(i);       
	}
}

void ProjectExplorer::on_btnClone_clicked()
{
    QModelIndexList l = ui->projectView->selectionModel()->selectedIndexes();
    if (l.isEmpty())
    {
            return;
    }
    sk::GameItem * item = reinterpret_cast<sk::GameItem *>(l.front().data().toLongLong());
    sk::GameItem * p = item->parent();
    if (0 == p || !p->canCloneChilds())
    {
        QMessageBox::critical(this, tr("Error"), tr("Can not clone this item"));
        return;
    }
    sk::SimpleItemParam pr;
    pr.type = sk::IT_CLONE;
    pr.ind  = item->index();
    pr.drop = p->index() == 1;
    _UD.mw->model()->create(p, &pr);
    sk::GameItem * i = p->child(p->numChilds() - 1);
    select(i);
    loadProperties(i);
    _UD.dw->updateScene(i, pr.drop);

}
